package com.kizitonwose.calendarview.fraction;

import ohos.aafwk.content.Intent;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AbsButton;
import ohos.agp.components.Checkbox;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.ComponentTreeObserver;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;

import com.kizitonwose.calendarview.CalendarView;
import com.kizitonwose.calendarview.ResourceTable;
import com.kizitonwose.calendarview.model.CalendarDay;
import com.kizitonwose.calendarview.model.CalendarMonth;
import com.kizitonwose.calendarview.model.enums.DayOwner;
import com.kizitonwose.calendarview.model.enums.InDateStyle;
import com.kizitonwose.calendarview.ui.ViewContainer;
import com.kizitonwose.calendarview.uinterface.DayBinder;
import com.kizitonwose.calendarview.uinterface.MonthScrollListener;
import com.kizitonwose.calendarview.utils.ComparisonsUtil;
import com.kizitonwose.calendarview.utils.DayExtensions;
import com.kizitonwose.calendarview.utils.LocalDateExtension;
import com.kizitonwose.calendarview.utils.Log;
import com.kizitonwose.calendarview.utils.LogUtil;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author LiuQingHua
 * @version 1.0
 * @date 2021/2/18 17:59
 */
public class Example1Fraction extends BaseFraction {
    private static final String TAG = "Example1Fraction";
    private CalendarView exOneCalendar;
    private List<LocalDate> selectedDates = new ArrayList<>();
    private LocalDate today = LocalDate.now();
    private DateTimeFormatter monthTitleFormatter = DateTimeFormatter.ofPattern("MMMM");
    private ComponentContainer legendLayout;
    private Text exOneYearText;
    private Text exOneMonthText;
    private Checkbox weekModeCheckBox;
    private ShapeElement elementTransparent = new ShapeElement();
    private AnimatorValue animatedValue;
    private LocalDate mLastFirstDate;
    private LocalDate mLastLastDate;

    @Override
    protected int getLayoutResId() {
        return ResourceTable.Layout_example_1_fraction;
    }

    @Override
    protected int getStatusBarColor() {
        return mContext.getColor(ResourceTable.Color_example_1_bg_light);
    }

    @Override
    protected void initComponent(Component content, ComponentContainer container, Intent intent) {
        animatedValue = new AnimatorValue();
        exOneCalendar = findComponentById(ResourceTable.Id_exOneCalendar);
        exOneYearText = findComponentById(ResourceTable.Id_exOneYearText);
        exOneMonthText = findComponentById(ResourceTable.Id_exOneMonthText);
        weekModeCheckBox = findComponentById(ResourceTable.Id_weekModeCheckBox);
        legendLayout = findComponentById(ResourceTable.Id_legendLayout);
        //设置背景颜色
        ShapeElement shapeElement = new ShapeElement(mContext, ResourceTable.Graphic_example_1_bg_light_shape);
        legendLayout.setBackground(shapeElement);
        DayOfWeek[] daysOfWeek = DayExtensions.daysOfWeekFromLocale();
        int childCount = legendLayout.getChildCount();
        for (int i = 0; i < childCount; i++) {
            Text text = (Text) legendLayout.getComponentAt(i);
            text.setText(daysOfWeek[i].getDisplayName(TextStyle.SHORT, Locale.ENGLISH).toUpperCase(Locale.ENGLISH));
            try {
                text.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_1_white_light).getColor()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        YearMonth currentMonth = YearMonth.now();
        YearMonth startMonth = currentMonth.minusMonths(10);
        YearMonth endMonth = currentMonth.plusMonths(10);
        exOneCalendar.setup(startMonth, endMonth, daysOfWeek[0]);
        exOneCalendar.scrollToMonth(currentMonth);
        exOneCalendar.setDayBinder(new DayBinder<DayViewContainer>() {

            @Override
            public DayViewContainer create(Component component) {
                return new DayViewContainer(component);
            }

            @Override
            public void bind(DayViewContainer container, CalendarDay day) {
                try {
                    container.day = day;
                    Text textView = container.textView;
                    textView.setText(String.valueOf(day.getDate().getDayOfMonth()));
                    if (day.getOwner() == DayOwner.THIS_MONTH) {
                        if (selectedDates.contains(day.getDate())) {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_1_bg).getColor()));
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_1_selected_bg);
                            textView.setBackground(element);
                        } else if (day.getDate().isEqual(today)) {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_1_white).getColor()));
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_1_today_bg);
                            textView.setBackground(element);
                        } else {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_1_white).getColor()));
                            textView.setBackground(elementTransparent);
                        }
                    } else {
                        textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_1_white_light).getColor()));
                        textView.setBackground(elementTransparent);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        exOneCalendar.setMonthScrollListener(new MonthScrollListener() {
            @Override
            public void onMonthScroll(CalendarMonth calendarMonth) {
                int month = calendarMonth.getMonth();
                int year = calendarMonth.getYear();
                LogUtil.info(TAG , "exOneCalendar.getMaxRowCount() == "+exOneCalendar.getMaxRowCount());
                LogUtil.info(TAG , "year == "+year);
                LogUtil.info(TAG , "month == "+month);
                if (exOneCalendar.getMaxRowCount() == 6) {
                    exOneYearText.setText(String.valueOf(calendarMonth.getYearMonth().getYear()));
                    exOneMonthText.setText(monthTitleFormatter.format(calendarMonth.getYearMonth()));
                } else {
                    // In week mode, we show the header a bit differently.
                    // We show indices with dates from different months since
                    // dates overflow and cells in one index can belong to different
                    // months/years.
                    List<List<CalendarDay>> weekDays = calendarMonth.getWeekDays();
                    LocalDate firstDate = weekDays.get(0).get(0).getDate();
                    List<CalendarDay> days = weekDays.get(weekDays.size() - 1);
                    LocalDate lastDate = days.get(days.size() - 1).getDate();
                    if (LocalDateExtension.getInstance(firstDate).getYearMonth().compareTo(LocalDateExtension.getInstance(lastDate).getYearMonth()) == 0) {
                        LogUtil.info(TAG , "111111");
                        exOneYearText.setText(String.valueOf(LocalDateExtension.getInstance(firstDate).getYearMonth().getYear()));
                        exOneMonthText.setText(monthTitleFormatter.format(firstDate));
                    } else {
                        LogUtil.info(TAG , "222222");
                        exOneMonthText.setText(String.format("%s - %s", monthTitleFormatter.format(firstDate), monthTitleFormatter.format(lastDate)));
                        if (firstDate.getYear() == lastDate.getYear()) {
                            exOneYearText.setText(String.valueOf(LocalDateExtension.getInstance(firstDate).getYearMonth().getYear()));
                        } else {
                            exOneYearText.setText(String.format("%s - %s", LocalDateExtension.getInstance(firstDate).getYearMonth().getYear(), LocalDateExtension.getInstance(lastDate).getYearMonth().getYear()));
                        }
                    }
                }
            }
        });
        weekModeCheckBox.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() {
            @Override
            public void onCheckedChanged(AbsButton absButton, boolean monthToWeek) {
                LogUtil.debug(TAG , "monthToWeek == "+monthToWeek);
                if (animatedValue == null) {
                    animatedValue = new AnimatorValue();
                }
                exOneCalendar.setAnimating(false);
                LocalDate firstDate;
                LocalDate lastDate;
                if (exOneCalendar.isScroll()) {
                    firstDate = mLastFirstDate;
                    lastDate = mLastLastDate;
                } else {
                    CalendarDay firstCalendarDay = exOneCalendar.findFirstVisibleDay();
                    CalendarDay lastCalendarDay = exOneCalendar.findLastVisibleDay();

                    if (firstCalendarDay == null || firstCalendarDay.getDate() == null) {
//                        weekModeCheckBox.setChecked(monthToWeek);
                        return;
                    }
                    if (lastCalendarDay == null || lastCalendarDay.getDate() == null) {
//                        weekModeCheckBox.setChecked(monthToWeek);
                        return;
                    }

                    firstDate = firstCalendarDay.getDate();
                    lastDate = lastCalendarDay.getDate();
                }

                int oneWeekHeight = exOneCalendar.getDaySize().getHeight();
                int oneMonthHeight = oneWeekHeight * 6;

                int oldHeight = monthToWeek ? oneMonthHeight : oneWeekHeight;
                int newHeight = monthToWeek ? oneWeekHeight : oneMonthHeight;
                // Animate calendar height changes.
                long animateDuration = 250;
                animatedValue.setDuration(animateDuration);
                animatedValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float v) {
                        // v 从 0到1
                        LogUtil.info(TAG , "onUpdate");
                        int height = (int) (oldHeight + v * (newHeight - oldHeight));
                        exOneCalendar.updateLayoutConfig(height);
                    }
                });

                // When changing from month to week mode, we change the calendar's
                // config at the end of the animation(doOnEnd) but when changing
                // from week to month mode, we change the calendar's config at
                // the start of the animation(doOnStart). This is so that the change
                // in height is visible. You can do this whichever way you prefer.
                animatedValue.setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                        weekModeCheckBox.setClickable(false);
                        exOneCalendar.setAnimating(true);

                        if (!monthToWeek) {
                            exOneCalendar.updateMonthConfiguration(InDateStyle.ALL_MONTHS, exOneCalendar.getOutDateStyle(), 6, true);
                        }
                    }

                    @Override
                    public void onStop(Animator animator) {

                    }

                    @Override
                    public void onCancel(Animator animator) {
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        exOneCalendar.setAnimating(false);
                        if (monthToWeek) {
                            exOneCalendar.updateMonthConfiguration(InDateStyle.FIRST_MONTH, exOneCalendar.getOutDateStyle(), 1, false);
                        }

                        if (monthToWeek) {
                            // We want the first visible day to remain
                            // visible when we change to week mode.
                            exOneCalendar.scrollToDate(firstDate);
                        } else {
                            // When changing to month mode, we choose current
                            // month if it is the only one in the current frame.
                            // if we have multiple months in one frame, we prefer
                            // the second one unless it's an outDate in the last index.
                            if (LocalDateExtension.getInstance(firstDate).getYearMonth().equals(LocalDateExtension.getInstance(lastDate).getYearMonth())) {
                                exOneCalendar.scrollToMonth(LocalDateExtension.getInstance(firstDate).getYearMonth());
                            } else {
                                // We compare the next with the last month on the calendar so we don't go over.
                                exOneCalendar.scrollToMonth(ComparisonsUtil.minOf(LocalDateExtension.getInstance(firstDate).getYearMonth().plusMonths(1), endMonth));
                            }
                        }
                        mLastFirstDate = firstDate;
                        mLastLastDate = lastDate;

                    }

                    @Override
                    public void onPause(Animator animator) {

                    }

                    @Override
                    public void onResume(Animator animator) {

                    }
                });
                animatedValue.start();
            }
        });

        exOneCalendar.setScrollListener(new ListContainer.ScrollListener() {
            @Override
            public void onScrollFinished() {
                weekModeCheckBox.setClickable(true);
            }
        });


    }

    class DayViewContainer extends ViewContainer {
        CalendarDay day;
        Text textView;

        public DayViewContainer(Component component) {
            super(component);
            textView = (Text) component.findComponentById(ResourceTable.Id_exOneDayText);
            textView.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (day.getOwner() == DayOwner.THIS_MONTH) {
                        if (selectedDates.contains(day.getDate())) {
                            selectedDates.remove(day.getDate());
                        } else {
                            selectedDates.add(day.getDate());
                        }
                        exOneCalendar.notifyDayChanged(day);
                    }
                }

            });

        }
    }
}
